// @Author EthanScriptOn
// @Desc
package config_source_loader_management

import (
	"errors"
	"gitee.com/fatzeng/srf_switch_basic_components/initialization"
	"gitee.com/fatzeng/srf_switch_config/config_define"
	"gitee.com/fatzeng/srf_switch_config/config_freighter"
	"gitee.com/fatzeng/srf_switch_config/config_processor"
	"gitee.com/fatzeng/srf_switch_config/config_source_loader"
	"math"
	"reflect"
)

type SupportList struct {
	List      map[config_define.ConfigSourceType]*SourceProcessorConfiguration
	Freighter reflect.Type
}

var supportedList = func() *initialization.OnceInitializer {
	initializer := initialization.GenerateOnceInitializer(config_define.ParserPositionTag, config_define.SupportedListInitTag)
	err := initializer.Set(math.MaxInt, func() (result interface{}, err error) {
		return &SupportList{
			List: map[config_define.ConfigSourceType]*SourceProcessorConfiguration{
				config_define.YAML: {
					SourceLoaderType: reflect.TypeOf(config_source_loader.YamlFileSourceLoader{}),
					ProcessorType:    reflect.TypeOf(config_processor.YamlIntegration{}),
				},
				config_define.PROPERTIES: {
					SourceLoaderType: reflect.TypeOf(config_source_loader.PropFileSourceLoader{}),
					ProcessorType:    reflect.TypeOf(config_processor.PropertiesIntegration{}),
				},
				config_define.INI: {
					SourceLoaderType: reflect.TypeOf(config_source_loader.IniFileSourceLoader{}),
					ProcessorType:    reflect.TypeOf(config_processor.IniIntegration{}),
				},
				config_define.ENV: {
					SourceLoaderType: reflect.TypeOf(config_source_loader.EnvVariableSourceLoader{}),
					ProcessorType:    reflect.TypeOf(config_processor.EnvIntegration{}),
				},
				config_define.CLI: {
					SourceLoaderType: reflect.TypeOf(config_source_loader.CliSourceLoader{}),
					ProcessorType:    reflect.TypeOf(config_processor.CliIntegration{}),
				},
			},
			Freighter: reflect.TypeOf(config_freighter.FreighterConfigurator{}),
		}, nil
	})
	if err != nil {
		panic(err)
	}
	return initializer
}()

func GetSupportedList() (map[config_define.ConfigSourceType]*SourceProcessorConfiguration, error) {
	supportListInstance, err := supportedList.Get()
	if err != nil {
		return nil, err
	}
	getList, ok := supportListInstance.(*SupportList)
	if !ok {
		return nil, errors.New("the supportedList type must be *SupportList")
	}
	return getList.List, nil
}

func GetSupportedFreighter() (reflect.Type, error) {
	supportListInstance, err := supportedList.Get()
	if err != nil {
		return nil, err
	}
	getList, ok := supportListInstance.(*SupportList)
	if !ok {
		return nil, errors.New("the supportedList type must be *SupportList")
	}
	return getList.Freighter, nil
}

var mainSourceLoaderManager = func() *initialization.OnceInitializer {
	initializer := initialization.GenerateOnceInitializer(config_define.ParserPositionTag, config_define.MainSourceLoaderManagerInitTag)
	err := initializer.Set(math.MaxInt, func() (result interface{}, err error) {
		sourceLoadersInstance, err := mainSourceLoaders.Get()
		if err != nil {
			return nil, err
		}
		sl := sourceLoadersInstance.(config_source_loader.SourceLoaders)
		return GenerateSourceLoaderManager(sl), nil
	})
	if err != nil {
		panic(err)
	}
	return initializer
}()

func GetMainSourceLoaderManager() (SourceLoaderManager, error) {
	mainSourceLoaderManagerInstance, err := mainSourceLoaderManager.Get()
	if err != nil {
		return nil, err
	}
	mainSourceLoaderManagerConversionInstance, ok := mainSourceLoaderManagerInstance.(SourceLoaderManager)
	if !ok {
		return nil, errors.New("the type must be SourceLoaderManager")
	}
	return mainSourceLoaderManagerConversionInstance, nil
}
